package com.bix.util.blizfiles.m2;

import java.nio.ByteBuffer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * This is the M2FileHeader class and is documented on the wowdev.org wiki.
 * 
 * @author squid
 * 
 * @link	http://wowdev.org/wiki/index.php/M2#Header
 */
public class M2FileHeader {
	private Log log = LogFactory.getLog(M2FileHeader.class);
	
	//
	// MD10 or MD20
	//
	private	byte	magic[] = new byte[4];

	//
	// Version of the file.
	//
	private	int		version;
	
	//
	// Name of the model.  Length includes the \0.
	//
	private	M2CountOffsetPair	modelName = new M2CountOffsetPair ();
	
	//
	// Type of model (0, 1, or 3 -- mostly 0).
	//
	private	int							modelType;
	
	private	M2CountOffsetPair	globalSequences = new M2CountOffsetPair ();
	private	M2CountOffsetPair	animations = new M2CountOffsetPair ();
	private	M2CountOffsetPair	animationLookups = new M2CountOffsetPair ();
	private	M2CountOffsetPair	bones = new M2CountOffsetPair ();
	private	M2CountOffsetPair	keyBoneLookupTable = new M2CountOffsetPair ();
	private	M2CountOffsetPair	vertices = new M2CountOffsetPair ();
	private	int								views;
	private	M2CountOffsetPair	colors = new M2CountOffsetPair ();
	private	M2CountOffsetPair	textures = new M2CountOffsetPair ();
	private	M2CountOffsetPair	transparencies = new M2CountOffsetPair ();
	private	M2CountOffsetPair	textureAnimations = new M2CountOffsetPair ();
	private	M2CountOffsetPair	replaceableTextures = new M2CountOffsetPair ();
	private	M2CountOffsetPair	renderFlags = new M2CountOffsetPair ();
	private	M2CountOffsetPair	boneLookupTable = new M2CountOffsetPair ();
	private	M2CountOffsetPair	textureLookupEntries = new M2CountOffsetPair ();
	private	M2CountOffsetPair	textureUnits = new M2CountOffsetPair ();
	private	M2CountOffsetPair	transparencyLookEntries = new M2CountOffsetPair ();
	private	M2CountOffsetPair	textureAnimationLookupEntries = new M2CountOffsetPair ();
	private	float							floats[] = new float[14];
	private	M2CountOffsetPair	boundingTriangles = new M2CountOffsetPair ();
	private	M2CountOffsetPair	boundingVertices = new M2CountOffsetPair ();
	private	M2CountOffsetPair	boundingNormals = new M2CountOffsetPair ();
	private	M2CountOffsetPair	attachments = new M2CountOffsetPair ();
	private	M2CountOffsetPair	attachmentLookups = new M2CountOffsetPair ();
	private	M2CountOffsetPair	attachments2 = new M2CountOffsetPair ();
	private	M2CountOffsetPair	lights = new M2CountOffsetPair ();
	private	M2CountOffsetPair	cameras = new M2CountOffsetPair ();
	private	M2CountOffsetPair	cameraLookup = new M2CountOffsetPair ();
	private	M2CountOffsetPair	ribbonEmitters = new M2CountOffsetPair ();
	private	M2CountOffsetPair	particleEmitters = new M2CountOffsetPair ();
	
	public M2FileHeader () {
	}
	
	public void read (ByteBuffer bb) throws M2FileException {
		//
		// Read the magic value and make sure it's either MD10 or MD20.
		//
		bb.get (this.magic);
		if (this.magic[0] != 'M'		||
				this.magic[1] != 'D'		||
				(this.magic[2] != '1'	&& this.magic[2] != '2')	||
				this.magic[3] != '0') {
			throw new M2FileException ("Invalid magic value received:  " + new String (this.magic, 0, 4));
		}
		
		this.version = bb.getInt();
		this.modelName.read (bb);
		this.modelType = bb.getInt();				// 0, 1, or 3... usually 0
		
		this.globalSequences.read (bb);
		this.animations.read (bb);
		this.animationLookups.read (bb);
		this.bones.read (bb);
		this.keyBoneLookupTable.read (bb);
		this.vertices.read (bb);
		this.views = bb.getInt ();
		
		this.colors.read (bb);
		this.textures.read (bb);
		this.transparencies.read (bb);
		this.textureAnimations.read (bb);
		this.replaceableTextures.read (bb);
		this.renderFlags.read (bb);
		this.boneLookupTable.read (bb);
		this.textureLookupEntries.read (bb);
		this.textureUnits.read (bb);
		this.transparencyLookEntries.read (bb);
		this.textureAnimationLookupEntries.read (bb);
		
		for (int i = 0; i < 14; i++) {
			floats[i] = bb.getFloat();
		}
		this.boundingTriangles.read (bb);
		this.boundingVertices.read (bb);
		this.boundingNormals.read (bb);
		this.attachments.read (bb);
		this.attachmentLookups.read (bb);
		this.attachments2.read (bb);
		this.lights.read (bb);
		this.cameras.read (bb);
		this.cameraLookup.read (bb);
		this.ribbonEmitters.read (bb);
		this.particleEmitters.read (bb);		
		
		log.debug ("Model Version[0x" + Integer.toHexString (this.version) + "]");
		log.debug ("Model Name Count/Offset[" + this.modelName.getCount() + ",0x" + Integer.toHexString (this.modelName.getOffset ()) + "]");
		log.debug ("Model Type[" + this.modelType + "]");
		log.debug ("Global Sequences Count/Offset[" + this.globalSequences.getCount() + ",0x" + Integer.toHexString (this.globalSequences.getOffset ()) + "]");
		log.debug ("Animations Count/Offset[" + this.animations.getCount() + ",0x" + Integer.toHexString (this.animations.getOffset ()) + "]");
		log.debug ("Animation Lookups Count/Offset[" + this.animationLookups.getCount() + ",0x" + Integer.toHexString (this.animationLookups.getOffset ()) + "]");
		log.debug ("Bone Count/Offset[" + this.bones.getCount() + ",0x" + Integer.toHexString (this.bones.getOffset ()) + "]");
		log.debug ("Key Bone Lookup Table Count/Offset[" + this.keyBoneLookupTable.getCount() + ",0x" + Integer.toHexString (this.keyBoneLookupTable.getOffset ()) + "]");
		log.debug ("Vertices Count/Offset[" + this.vertices.getCount() + ",0x" + Integer.toHexString (this.vertices.getOffset ()) + "]");
		log.debug ("Views [" + this.views + "]");
		log.debug ("Colors Count/Offset[" + this.colors.getCount() + ",0x" + Integer.toHexString (this.colors.getOffset ()) + "]");
		log.debug ("Textures Count/Offset[" + this.textures.getCount() + ",0x" + Integer.toHexString (this.textures.getOffset ()) + "]");
		log.debug ("Transparencies Count/Offset[" + this.transparencies.getCount() + ",0x" + Integer.toHexString (this.transparencies.getOffset ()) + "]");
		log.debug ("Texture Animations Count/Offset[" + this.textureAnimations.getCount() + ",0x" + Integer.toHexString (this.textureAnimations.getOffset ()) + "]");
		log.debug ("Replaceable Textures Count/Offset[" + this.replaceableTextures.getCount() + ",0x" + Integer.toHexString (this.replaceableTextures.getOffset ()) + "]");
		log.debug ("Render Flags Count/Offset[" + this.renderFlags.getCount() + ",0x" + Integer.toHexString (this.renderFlags.getOffset ()) + "]");
		log.debug ("Bone Lookup Table Count/Offset[" + this.boneLookupTable.getCount() + ",0x" + Integer.toHexString (this.boneLookupTable.getOffset ()) + "]");
		log.debug ("Texture Lookup Entries Count/Offset[" + this.textureLookupEntries.getCount() + ",0x" + Integer.toHexString (this.textureLookupEntries.getOffset ()) + "]");
		log.debug ("Texture Units Count/Offset[" + this.textureUnits.getCount() + ",0x" + Integer.toHexString (this.textureUnits.getOffset ()) + "]");
		log.debug ("Transaprency Lookup Entries Count/Offset[" + this.transparencyLookEntries.getCount() + ",0x" + Integer.toHexString (this.transparencyLookEntries.getOffset ()) + "]");
		log.debug ("Texture Animation Lookup Entries Count/Offset[" + this.textureAnimationLookupEntries.getCount() + ",0x" + Integer.toHexString (this.textureAnimationLookupEntries.getOffset ()) + "]");
		log.debug ("Bounding Triangles Count/Offset[" + this.boundingTriangles.getCount() + ",0x" + Integer.toHexString (this.boundingTriangles.getOffset ()) + "]");
		log.debug ("Bounding Vertices Count/Offset[" + this.boundingVertices.getCount() + ",0x" + Integer.toHexString (this.boundingVertices.getOffset ()) + "]");
		log.debug ("Bounding Normals Count/Offset[" + this.boundingNormals.getCount() + ",0x" + Integer.toHexString (this.boundingNormals.getOffset ()) + "]");
		log.debug ("Attachments Count/Offset[" + this.attachments.getCount() + ",0x" + Integer.toHexString (this.attachments.getOffset ()) + "]");
		log.debug ("Attachment Lookups Count/Offset[" + this.attachmentLookups.getCount() + ",0x" + Integer.toHexString (this.attachmentLookups.getOffset ()) + "]");
		log.debug ("Attachments2 Count/Offset[" + this.attachments2.getCount() + ",0x" + Integer.toHexString (this.attachments2.getOffset ()) + "]");
		log.debug ("Lights Count/Offset[" + this.lights.getCount() + ",0x" + Integer.toHexString (this.lights.getOffset ()) + "]");
		log.debug ("Cameras Count/Offset[" + this.cameras.getCount() + ",0x" + Integer.toHexString (this.cameras.getOffset ()) + "]");
		log.debug ("Camera Lookups Count/Offset[" + this.cameraLookup.getCount() + ",0x" + Integer.toHexString (this.cameraLookup.getOffset ()) + "]");
		log.debug ("Ribbon Emitters Count/Offset[" + this.ribbonEmitters.getCount() + ",0x" + Integer.toHexString (this.ribbonEmitters.getOffset ()) + "]");
		log.debug ("Particle Emitters Count/Offset[" + this.particleEmitters.getCount() + ",0x" + Integer.toHexString (this.particleEmitters.getOffset ()) + "]");
	}

	/**
	 * @return the magic
	 */
	public byte[] getMagic() {
		return magic;
	}

	/**
	 * @return the version
	 */
	public int getVersion() {
		return version;
	}

	/**
	 * @return the modelName
	 */
	public M2CountOffsetPair getModelName() {
		return modelName;
	}

	/**
	 * @return the modelType
	 */
	public int getModelType() {
		return modelType;
	}

	/**
	 * @return the globalSequences
	 */
	public M2CountOffsetPair getGlobalSequences() {
		return globalSequences;
	}

	/**
	 * @return the animations
	 */
	public M2CountOffsetPair getAnimations() {
		return animations;
	}

	/**
	 * @return the animationLookups
	 */
	public M2CountOffsetPair getAnimationLookups() {
		return animationLookups;
	}

	/**
	 * @return the bones
	 */
	public M2CountOffsetPair getBones() {
		return bones;
	}

	/**
	 * @return the keyBoneLookupTable
	 */
	public M2CountOffsetPair getKeyBoneLookupTable() {
		return keyBoneLookupTable;
	}

	/**
	 * @return the vertices
	 */
	public M2CountOffsetPair getVertices() {
		return vertices;
	}

	/**
	 * @return the views
	 */
	public int getViews() {
		return views;
	}

	/**
	 * @return the colors
	 */
	public M2CountOffsetPair getColors() {
		return colors;
	}

	/**
	 * @return the textures
	 */
	public M2CountOffsetPair getTextures() {
		return textures;
	}

	/**
	 * @return the transparencies
	 */
	public M2CountOffsetPair getTransparencies() {
		return transparencies;
	}

	/**
	 * @return the textureAnimations
	 */
	public M2CountOffsetPair getTextureAnimations() {
		return textureAnimations;
	}

	/**
	 * @return the replaceableTextures
	 */
	public M2CountOffsetPair getReplaceableTextures() {
		return replaceableTextures;
	}

	/**
	 * @return the renderFlags
	 */
	public M2CountOffsetPair getRenderFlags() {
		return renderFlags;
	}

	/**
	 * @return the boneLookupTable
	 */
	public M2CountOffsetPair getBoneLookupTable() {
		return boneLookupTable;
	}

	/**
	 * @return the textureLookupEntries
	 */
	public M2CountOffsetPair getTextureLookupEntries() {
		return textureLookupEntries;
	}

	/**
	 * @return the textureUnits
	 */
	public M2CountOffsetPair getTextureUnits() {
		return textureUnits;
	}

	/**
	 * @return the transparencyLookEntries
	 */
	public M2CountOffsetPair getTransparencyLookEntries() {
		return transparencyLookEntries;
	}

	/**
	 * @return the textureAnimationLookupEntries
	 */
	public M2CountOffsetPair getTextureAnimationLookupEntries() {
		return textureAnimationLookupEntries;
	}

	/**
	 * @return the floats
	 */
	public float[] getFloats() {
		return floats;
	}

	/**
	 * @return the boundingTriangles
	 */
	public M2CountOffsetPair getBoundingTriangles() {
		return boundingTriangles;
	}

	/**
	 * @return the boundingVertices
	 */
	public M2CountOffsetPair getBoundingVertices() {
		return boundingVertices;
	}

	/**
	 * @return the boundingNormals
	 */
	public M2CountOffsetPair getBoundingNormals() {
		return boundingNormals;
	}

	/**
	 * @return the attachments
	 */
	public M2CountOffsetPair getAttachments() {
		return attachments;
	}

	/**
	 * @return the attachmentLookups
	 */
	public M2CountOffsetPair getAttachmentLookups() {
		return attachmentLookups;
	}

	/**
	 * @return the attachments2
	 */
	public M2CountOffsetPair getAttachments2() {
		return attachments2;
	}

	/**
	 * @return the lights
	 */
	public M2CountOffsetPair getLights() {
		return lights;
	}

	/**
	 * @return the cameras
	 */
	public M2CountOffsetPair getCameras() {
		return cameras;
	}

	/**
	 * @return the cameraLookup
	 */
	public M2CountOffsetPair getCameraLookup() {
		return cameraLookup;
	}

	/**
	 * @return the ribbonEmitters
	 */
	public M2CountOffsetPair getRibbonEmitters() {
		return ribbonEmitters;
	}

	/**
	 * @return the particleEmitters
	 */
	public M2CountOffsetPair getParticleEmitters() {
		return particleEmitters;
	}
}

